/**
 @file sys_usw_linkagg.h

 @date 2009-10-19

 @version v2.0

 The file define APIs and types use in sys layer
*/
#ifndef _SYS_USW_LINKAGG_H
#define _SYS_USW_LINKAGG_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************
 *
 * Header Files
 *
 ***************************************************************/
#include "sal.h"
#include "ctc_const.h"
#include "ctc_vector.h"
#include "ctc_common.h"

#include "ctc_linkagg.h"
/***************************************************************
 *
 *  Defines and Macros
 *
 ***************************************************************/
/* member num in all linkAgg groups */

#define SYS_DLB_DOWN_FRE_RATE  1
#define SYS_DLB_TS_THRES 200
#define SYS_DLB_MAX_PTR 1999
#define SYS_DLB_MAX_PTR_TMM 9999
#define SYS_DLB_UPDATE_THRES 10000
#define SYS_DLB_TIMER_INTERVAL 3
#define SYS_LINKAGG_LB_HASH_MAX    256
#define SYS_LINKAGG_CHAN_HASH_MAX 32
#define SYS_LINKAGG_LSH_PORTS_MAX    8
#define SYS_LINKAGG_SPM_TBL_BASE_WIDTH 13
#define SYS_LINKAGG_MIRROR_MEMBER_NUM_MAX 8
#define SYS_LINKAGG_RR_COUNT_MAX 16


#define SYS_LINKAGG_OP_ADD 0
#define SYS_LINKAGG_OP_DEL 1
#define SYS_LINKAGG_OP_REP 2
#define SYS_LINKAGG_OP_CLR 3

/**
 @brief linkagg member number
*/
enum sys_linkagg_mem_num_e
{
    SYS_LINKAGG_MEM_NUM_1 = 24,     /* 24  members in linkAgg group */
    SYS_LINKAGG_MEM_NUM_2 = 32,     /* 32 members in linkAgg group */
    SYS_LINKAGG_MEM_NUM_3 = 64,     /* 64 members in linkAgg group */
    SYS_LINKAGG_MEM_NUM_4 = 128     /* 128 members in linkAgg group */
};
typedef enum sys_linkagg_mem_num_e sys_linkagg_mem_num_t;

/* member port info */
struct sys_linkagg_port_s
{
    uint32 valid  :1;        /* member port is in linkAgg group*/
    uint32 is_local : 1;      /* member port is lmpf enable in linkAgg group*/
    uint32 nonuc_block_en : 1;
    uint32 rsv : 29;
    uint32 gport;       /* member port */
};
typedef struct sys_linkagg_port_s sys_linkagg_port_t;

/* linkAgg group info */
struct sys_linkagg_s
{
    sys_linkagg_port_t** port_list;

    uint16 tid;             /* linkAggId */
    uint16 member_base;
    uint16 port_cnt;
    uint16 local_port_cnt;
    uint16 max_member_num;
    uint16 real_member_num; /*local uc  member number*/

    uint16 mirror_ref_cnt;  /*count of mirror use this group*/
    uint8 flag;             /*ctc_linkagg_group_flag_t*/
    uint8 xfabric_type;     /*AT, 0:NONE;1:profile0;2:profile1*/

    uint8 ref_cnt;          /*for channel linkagg, bpe cb cascade*/
    uint8 mode;             /*ctc_linkagg_group_mode_t*/
    uint8 lsh_mode;         /*ctc_linkagg_lsh_mode_t*/
    uint8 cfg_lmpf:1;
    uint8 is_lag  :1;       /*1: add/remove member donot process mc linkagg property*/
    uint8 rsv     :6;
};
typedef struct sys_linkagg_s sys_linkagg_t;

struct sys_linkagg_master_s
{
    sal_mutex_t* p_linkagg_mutex;
    ctc_vector_t* group_vector;
    ctc_vector_t* chan_group;

    uint32 rr_profile_bmp;

    uint8 opf_type;
    uint8 tx_load_percent;
    uint8 linkagg_mode;           /*ctc_linkagg_mode_t*/
    uint8 bind_gport_disable:1;   /** If set indicate the gport won't be configured automatically when the member port is added. */
    uint8 xfabric_en        :1;   /**< [AT]  0:None; 1: xFabric (default: 0)*/
    uint8 rsv               :6;
};
typedef struct sys_linkagg_master_s sys_linkagg_master_t;

#define SYS_LINKAGG_DBG_OUT(level, FMT, ...) \
    do { \
        CTC_DEBUG_OUT(linkagg, linkagg, LINKAGG_SYS, level, FMT, ##__VA_ARGS__); \
    } while (0);

#define SYS_LINKAGG_INIT_CHECK() \
    do { \
        LCHIP_CHECK(lchip);       \
        if (NULL == p_usw_linkagg_master[lchip]){ \
            SYS_LINKAGG_DBG_OUT(CTC_DEBUG_LEVEL_INFO, " Feature not initialized \n");\
            return CTC_E_NOT_INIT;\
 } \
    } while (0)

extern sys_linkagg_master_t* p_usw_linkagg_master[CTC_MAX_LOCAL_CHIP_NUM_PP] ;
/***************************************************************
 *
 *  Functions
 *
 ***************************************************************/
extern int32
sys_usw_linkagg_init(uint8 lchip, void* linkagg_global_cfg);

extern int32
sys_usw_linkagg_deinit(uint8 lchip);

extern int32
sys_usw_linkagg_create(uint8 lchip, ctc_linkagg_group_t* p_linkagg_grp);

extern int32
sys_usw_linkagg_destroy(uint8 lchip, uint16 tid);

extern int32
sys_usw_linkagg_set_property(uint8 lchip, uint16 tid, ctc_linkagg_property_t linkagg_prop, uint32 value);

extern int32
sys_usw_linkagg_get_property(uint8 lchip, uint16 tid, ctc_linkagg_property_t linkagg_prop, uint32* p_value);

extern int32
sys_usw_linkagg_add_port(uint8 lchip, uint16 tid, uint32 gport);

extern int32
sys_usw_linkagg_remove_port(uint8 lchip, uint16 tid, uint32 gport);

extern int32
sys_usw_linkagg_add_ports(uint8 lchip, uint16 tid, uint32 member_cnt, ctc_linkagg_port_t* p_ports);

extern int32
sys_usw_linkagg_remove_ports(uint8 lchip, uint16 tid, uint32 member_cnt, ctc_linkagg_port_t* p_ports);

extern int32
sys_usw_linkagg_get_1st_local_port(uint8 lchip, uint16 tid, uint32* p_gport, uint16* local_cnt);

extern int32
sys_usw_linkagg_get_ports(uint8 lchip, uint16 tid, uint32* p_gports, uint16* cnt);

extern int32
sys_usw_linkagg_set_psc(uint8 lchip, ctc_linkagg_psc_t* p_psc);

extern int32
sys_usw_linkagg_get_psc(uint8 lchip, ctc_linkagg_psc_t* p_psc);

extern int32
sys_usw_linkagg_show_all_member(uint8 lchip, uint16 tid);

extern int32
sys_usw_linkagg_get_max_mem_num(uint8 lchip, uint16* max_num);

extern int32
sys_usw_linkagg_replace_ports(uint8 lchip, uint16 tid, uint32* gport, uint16 mem_num);

extern int32
sys_usw_linkagg_get_group_info(uint8 lchip, ctc_linkagg_group_t* p_linkagg_grp);


extern int32
sys_usw_linkagg_set_lsh(uint8 lchip, uint16 tid, uint32 fail_port, ctc_linkagg_lsh_t* port_array);

extern int32
sys_usw_linkagg_get_lsh(uint8 lchip, uint16 tid, uint32 fail_port, ctc_linkagg_lsh_t* port_array);

extern int32
_sys_usw_linkagg_add_port_to_db(uint8 lchip, void* p_lag_group, uint32 gport, uint8 nonuc_block_en,uint8 lmpf_en);

extern int32
_sys_usw_linkagg_remove_port_to_db(uint8 lchip, void* p_lag_group, uint32 gport);

extern int32
sys_usw_linkagg_get_channel_agg_info(uint8 lchip, uint32 chan_id, uint8* chanagg_id, uint8* chanagg_ref_cnt);

extern int32
sys_usw_linkagg_set_channel_agg_ref_cnt(uint8 lchip, uint8 tid, bool is_add);

extern int32
sys_usw_linkagg_get_pp_bmp(uint8 lchip, uint16 tid, uint16* pp_bmp);

extern int32
sys_usw_linkagg_get_ports2(uint8 lchip, uint16 tid, uint32* member_list, uint8* p_member_cnt);

extern int32
sys_usw_linkagg_bind_mirror(uint8 lchip, uint8 tid, uint8 is_add);

extern int32
sys_usw_linkagg_loop_chan_lag_en(uint8 lchip, uint32 enable);

extern int32
sys_usw_linkagg_get_member_with_hash(uint8 lchip, uint16 tid, uint16 hash_value, uint32 * member_port);

extern int32
sys_usw_linkagg_set_nonuc_ports(uint8 lchip, uint16 tid, uint32* p_gports, uint16 cnt);

extern int32
sys_usw_linkagg_get_nonuc_ports(uint8 lchip, uint16 tid, uint32* p_gports, uint16* p_cnt);

#ifdef __cplusplus
}
#endif

#endif

